package com.ruoyi.heytalk.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.constant.heytalk.CommonConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.heytalk.ImApply;
import com.ruoyi.common.core.domain.heytalk.ImFriend;
import com.ruoyi.common.core.domain.heytalk.ImUser;
import com.ruoyi.common.core.domain.heytalk.dto.AddFriendDTO;
import com.ruoyi.common.core.domain.heytalk.dto.HandleFriendDTO;
import com.ruoyi.common.core.domain.heytalk.vo.LoginImUser;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.service.HeyTalkTokenService;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.heytalk.mapper.ImApplyMapper;
import com.ruoyi.heytalk.netty.IChatForwardHandlerService;
import com.ruoyi.heytalk.service.IImApplyService;
import com.ruoyi.heytalk.service.IImFriendService;
import com.ruoyi.heytalk.service.IImUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 好友申请Service业务层处理
 * 
 * @author ruoyi
 * @since 2021-10-17
 */
@Slf4j
@Service
@DataSource(value = DataSourceType.SLAVE)
public class ImApplyServiceImpl extends ServicePlusImpl<ImApplyMapper, ImApply, ImApply> implements IImApplyService {

    @Resource
    private HeyTalkTokenService tokenService;

    @Resource
    private IImUserService userService;

    @Resource
    private IImFriendService friendService;

    @Resource
    private IChatForwardHandlerService chatForwardHandlerService;

    @Override
    @Transactional
    public AjaxResult<Void> addFriend(AddFriendDTO addFriendDTO) {
        try {
            LoginImUser loginImUser = tokenService.getLoginImUser(ServletUtils.getRequest());
            if (addFriendDTO.getFriendId().equals(loginImUser.getUserId())) {
                return AjaxResult.error(MessageUtils.message("heyTalk.user.apply.exist"));
            }
            ImUser imUser = userService.getOne(new LambdaQueryWrapper<ImUser>()
                    .eq(ImUser::getId, addFriendDTO.getFriendId())
                    .eq(ImUser::getStatus, CommonConstants.UserStatusEnum.DEACTIVATE.getCode()));
            if (Objects.isNull(imUser)) {
                return AjaxResult.error(MessageUtils.message("heyTalk.user.not.or.disable"));
            }
            //查询是否有申请记录
            ImApply info = this.getOne(new LambdaQueryWrapper<ImApply>()
                    .eq(ImApply::getUserId, loginImUser.getUserId())
                    .eq(ImApply::getFriendId, addFriendDTO.getFriendId())
                    .in(ImApply::getStatus, CommonConstants.ApplyBStatusEnum.AWAIT_VERIFY.getCode(), CommonConstants.BApplyStatusEnum.PENDING.getCode()));
            if (!Objects.isNull(info)) {
                return AjaxResult.error(MessageUtils.message("heyTalk.apply.exist"));
            }
            String uuId = IdUtil.fastSimpleUUID();
            //申请人的请求数据
            ImApply apply = ImApply.builder().userId(loginImUser.getUserId()).uuId(uuId)
                    .status(CommonConstants.ApplyBStatusEnum.AWAIT_VERIFY.getCode())
                    .statusRemark(CommonConstants.ApplyBStatusEnum.AWAIT_VERIFY.getName())
                    .build();
            BeanUtil.copyProperties(addFriendDTO, apply);
            //被申请人的请求数据
            ImApply beApply = ImApply.builder().userId(addFriendDTO.getFriendId())
                    .friendId(loginImUser.getUserId())
                    .status(CommonConstants.BApplyStatusEnum.PENDING.getCode())
                    .statusRemark(CommonConstants.BApplyStatusEnum.PENDING.getName())
                    .uuId(uuId).nickName(loginImUser.getUser().getNickName()).avatar(loginImUser.getUser().getAvatar()).build();
            if (!this.save(apply) || !this.save(beApply)) {
                throw new ServiceException("申请好友失败");
            }
            return AjaxResult.success();
        } catch (Exception e) {
            log.error("申请好友失败:{}", e);
            throw new ServiceException("申请好友失败");
        } finally {
            List<String> userList = new ArrayList<>();
            userList.add(addFriendDTO.getFriendId());
            chatForwardHandlerService.chat(userList, CommonConstants.DataTypeEnum.UPDATE_APPLY_LIST.getCode(), false, false, null);
        }
    }

    private LambdaQueryWrapper<ImApply> buildQueryWrapper(LoginImUser loginImUser) {
        LambdaQueryWrapper<ImApply> lqw = Wrappers.lambdaQuery();
        lqw.eq(ImApply::getUserId, loginImUser.getUserId());
        return lqw;
    }

    @Override
    public TableDataInfo<ImApply> applyPage() {
        LoginImUser loginImUser = tokenService.getLoginImUser(ServletUtils.getRequest());
        PagePlus<ImApply, ImApply> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(loginImUser));
        Long count = this.count(new LambdaQueryWrapper<ImApply>().eq(ImApply::getUserId, loginImUser.getUserId()).eq(ImApply::getStatus, CommonConstants.BApplyStatusEnum.PENDING.getCode()));
        return PageUtils.buildDataInfo(result, count);
    }

    @Override
    @Transactional
    public AjaxResult<Void> handleFriend(HandleFriendDTO handleFriendDTO) {
        try {
            LoginImUser loginImUser = tokenService.getLoginImUser(ServletUtils.getRequest());
            //被申请人的请求数据
            ImApply beApply = this.getOne(new LambdaQueryWrapper<ImApply>()
                    .eq(ImApply::getId, handleFriendDTO.getId())
                    .eq(ImApply::getStatus, CommonConstants.BApplyStatusEnum.PENDING.getCode()));
            if (Objects.isNull(beApply)) {
                return AjaxResult.error("该记录不存在");
            }
            //不是同意状态不处理
            if (!CommonConstants.BApplyStatusEnum.AGREE.getCode().equals(handleFriendDTO.getStatus())) {
                return AjaxResult.success();
            }
            //当初申请人的请求数据
            ImApply apply = this.getOne(new LambdaQueryWrapper<ImApply>()
                    .eq(ImApply::getUuId, beApply.getUuId())
                    .eq(ImApply::getUserId, beApply.getFriendId()));
            if (Objects.isNull(apply)) {
                throw new ServiceException("数据异常，处理好友申请失败");
            }
            //更新请求数据
            beApply.setNickRemark(handleFriendDTO.getNickRemark());
            beApply.setLookMe(handleFriendDTO.getLookMe());
            beApply.setLookHim(handleFriendDTO.getLookHim());
            beApply.setStatus(CommonConstants.BApplyStatusEnum.AGREE.getCode());
            beApply.setStatusRemark(CommonConstants.BApplyStatusEnum.AGREE.getName());

            apply.setStatus(CommonConstants.ApplyBStatusEnum.VERIFY_OK.getCode());
            apply.setStatusRemark(CommonConstants.ApplyBStatusEnum.VERIFY_OK.getName());
            if (!this.updateById(beApply)||!this.updateById(apply)) {
                throw new ServiceException("处理好友申请失败");
            }
            //对方好友昵称
            String applyNicRemark = StrUtil.isNotBlank(apply.getNickRemark())?apply.getNickRemark():apply.getNickName();
            String beApplyNicRemark = StrUtil.isNotBlank(beApply.getNickRemark())?beApply.getNickRemark():beApply.getNickName();
            //加入到对方好友列表
            boolean otherFriend = friendService.save(ImFriend.builder()
                    .friendId(apply.getFriendId())
                    .userId(apply.getUserId())
                    .nickRemark(applyNicRemark)
                    .nickRemarkPinYin(PinyinUtil.getFirstLetter(applyNicRemark, ""))
                    .nickRemarkInitial(getRemarkPinYinLetter(applyNicRemark))
                    .avatar(loginImUser.getUser().getAvatar())
                    .lookMe(apply.getLookMe())
                    .lookHim(apply.getLookHim()).build());
            //将对方加入到我的好友列表
            boolean myFriend = friendService.save(ImFriend.builder()
                    .friendId(beApply.getFriendId())
                    .userId(beApply.getUserId())
                    .nickRemark(beApplyNicRemark)
                    .nickRemarkPinYin(PinyinUtil.getFirstLetter(beApplyNicRemark, ""))
                    .nickRemarkInitial(getRemarkPinYinLetter(beApplyNicRemark))
                    .avatar(beApply.getAvatar())
                    .lookMe(beApply.getLookMe())
                    .lookHim(beApply.getLookHim()).build());
            if (!otherFriend || !myFriend) {
                throw new ServiceException("处理好友申请失败");
            }
            return AjaxResult.success();
        } catch (Exception e) {
            log.error("处理好友申请失败:{}", e);
            throw new ServiceException("处理好友申请失败");
        }
    }

    /**
     *
     * @param nickName 传入的字符串
     * @return 获取自定字符串的首字母转大写，不是英文字母的返回#号
     */
    private static String getRemarkPinYinLetter(String nickName) {
        if (StrUtil.isBlank(nickName)) {
            return "";
        }
        String firstPinYin = PinyinUtil.getFirstLetter(nickName, "").substring(0,1);
        boolean isLetter= firstPinYin.matches("[a-zA-Z]+");
        if (isLetter) {
            return firstPinYin.toUpperCase();
        }
        return "#";
    }

    public static void main(String[] args) {
        System.out.println(PinyinUtil.getFirstLetter("鲁班七号的备注", ""));
        System.out.println(getRemarkPinYinLetter("鲁班七号的备注"));;
    }

}
